using System;
using System.Collections.Generic;

namespace CSharpBasicsExamples
{
    // 多态示例：员工管理系统
    
    // 基类：员工
    public abstract class Employee
    {
        public string Name { get; set; }
        public int Id { get; set; }
        public DateTime HireDate { get; set; }
        
        protected Employee(string name, int id)
        {
            Name = name;
            Id = id;
            HireDate = DateTime.Now;
        }
        
        // 虚方法：计算工资
        public virtual decimal CalculateSalary()
        {
            return 0;
        }
        
        // 抽象方法：获取员工类型
        public abstract string GetEmployeeType();
        
        // 虚方法：工作描述
        public virtual void Work()
        {
            Console.WriteLine($"{Name} 正在工作...");
        }
        
        // 虚方法：获取福利
        public virtual string GetBenefits()
        {
            return "基本医疗保险";
        }
        
        public override string ToString()
        {
            return $"ID: {Id}, 姓名: {Name}, 类型: {GetEmployeeType()}";
        }
    }
    
    // 派生类：全职员工
    public class FullTimeEmployee : Employee
    {
        public decimal MonthlySalary { get; set; }
        public decimal Bonus { get; set; }
        
        public FullTimeEmployee(string name, int id, decimal monthlySalary) 
            : base(name, id)
        {
            MonthlySalary = monthlySalary;
            Bonus = 0;
        }
        
        public override decimal CalculateSalary()
        {
            return MonthlySalary + Bonus;
        }
        
        public override string GetEmployeeType()
        {
            return "全职员工";
        }
        
        public override void Work()
        {
            Console.WriteLine($"{Name} 作为全职员工正在全天工作，月薪: {MonthlySalary:C}");
        }
        
        public override string GetBenefits()
        {
            return base.GetBenefits() + ", 年假, 绩效奖金, 股票期权";
        }
        
        public void AttendMeeting()
        {
            Console.WriteLine($"{Name} 正在参加公司会议");
        }
    }
    
    // 派生类：兼职员工
    public class PartTimeEmployee : Employee
    {
        public decimal HourlyRate { get; set; }
        public int WorkHours { get; set; }
        
        public PartTimeEmployee(string name, int id, decimal hourlyRate) 
            : base(name, id)
        {
            HourlyRate = hourlyRate;
            WorkHours = 0;
        }
        
        public override decimal CalculateSalary()
        {
            return HourlyRate * WorkHours;
        }
        
        public override string GetEmployeeType()
        {
            return "兼职员工";
        }
        
        public override void Work()
        {
            Console.WriteLine($"{Name} 作为兼职员工工作{WorkHours}小时，时薪: {HourlyRate:C}");
        }
        
        public override string GetBenefits()
        {
            return base.GetBenefits() + ", 弹性工作时间";
        }
        
        public void SetWorkHours(int hours)
        {
            WorkHours = hours;
            Console.WriteLine($"{Name} 本月工作时间设置为: {hours} 小时");
        }
    }
    
    // 派生类：合同工
    public class ContractEmployee : Employee
    {
        public decimal ProjectFee { get; set; }
        public DateTime ContractEndDate { get; set; }
        
        public ContractEmployee(string name, int id, decimal projectFee, DateTime endDate) 
            : base(name, id)
        {
            ProjectFee = projectFee;
            ContractEndDate = endDate;
        }
        
        public override decimal CalculateSalary()
        {
            return ProjectFee;
        }
        
        public override string GetEmployeeType()
        {
            return "合同工";
        }
        
        public override void Work()
        {
            var remainingDays = (ContractEndDate - DateTime.Now).Days;
            Console.WriteLine($"{Name} 作为合同工正在完成项目，项目费用: {ProjectFee:C}，剩余天数: {remainingDays}");
        }
        
        public override string GetBenefits()
        {
            return "项目完成奖金";
        }
        
        public bool IsContractExpired()
        {
            return DateTime.Now > ContractEndDate;
        }
    }
    
    // 使用多态的薪资系统
    public class PayrollSystem
    {
        private List<Employee> employees;
        
        public PayrollSystem()
        {
            employees = new List<Employee>();
        }
        
        public void AddEmployee(Employee employee)
        {
            employees.Add(employee);
            Console.WriteLine($"员工 {employee.Name} 已添加到系统中");
        }
        
        public void ProcessPayroll()
        {
            Console.WriteLine("\n=== 薪资处理系统 ===");
            decimal totalPayroll = 0;
            
            foreach (Employee emp in employees)
            {
                // 多态调用：根据实际对象类型调用相应的方法
                Console.WriteLine($"\n员工信息: {emp}");
                Console.WriteLine($"工资: {emp.CalculateSalary():C}");
                Console.WriteLine($"福利: {emp.GetBenefits()}");
                emp.Work();
                
                totalPayroll += emp.CalculateSalary();
                Console.WriteLine("---");
            }
            
            Console.WriteLine($"\n总薪资支出: {totalPayroll:C}");
        }
        
        public void ShowEmployeesByType<T>() where T : Employee
        {
            Console.WriteLine($"\n=== {typeof(T).Name} 列表 ===");
            foreach (Employee emp in employees)
            {
                if (emp is T)
                {
                    Console.WriteLine($"- {emp.Name} ({emp.GetEmployeeType()})");
                }
            }
        }
        
        public decimal GetTotalSalaryByType<T>() where T : Employee
        {
            decimal total = 0;
            foreach (Employee emp in employees)
            {
                if (emp is T)
                {
                    total += emp.CalculateSalary();
                }
            }
            return total;
        }
    }
    
    // 演示程序
    public class PolymorphismDemo
    {
        public static void RunDemo()
        {
            var payrollSystem = new PayrollSystem();
            
            // 创建不同类型的员工
            var fullTimeEmp = new FullTimeEmployee("张三", 1001, 8000);
            fullTimeEmp.Bonus = 2000;
            
            var partTimeEmp = new PartTimeEmployee("李四", 1002, 50);
            partTimeEmp.SetWorkHours(80);
            
            var contractEmp = new ContractEmployee("王五", 1003, 15000, DateTime.Now.AddMonths(3));
            
            // 添加员工到系统
            payrollSystem.AddEmployee(fullTimeEmp);
            payrollSystem.AddEmployee(partTimeEmp);
            payrollSystem.AddEmployee(contractEmp);
            
            // 处理薪资（展示多态）
            payrollSystem.ProcessPayroll();
            
            // 按类型显示员工
            payrollSystem.ShowEmployeesByType<FullTimeEmployee>();
            payrollSystem.ShowEmployeesByType<PartTimeEmployee>();
            
            // 计算各类型员工的总薪资
            Console.WriteLine($"\n全职员工总薪资: {payrollSystem.GetTotalSalaryByType<FullTimeEmployee>():C}");
            Console.WriteLine($"兼职员工总薪资: {payrollSystem.GetTotalSalaryByType<PartTimeEmployee>():C}");
            Console.WriteLine($"合同工总薪资: {payrollSystem.GetTotalSalaryByType<ContractEmployee>():C}");
            
            // 演示特定类型的方法调用
            Console.WriteLine("\n=== 特定方法调用 ===");
            fullTimeEmp.AttendMeeting();
            partTimeEmp.SetWorkHours(100);
            Console.WriteLine($"合同是否过期: {contractEmp.IsContractExpired()}");
        }
    }
}
